Ruby is a great language. All can be expressed so short and readable. That’s one side.
The other side is: you have to learn a lot of exceptions to common stuff that you already learned in another languages (In my case Java).
So today I will explain things where it took me a lot of time to understand how to do this and what ruby (and rails) does. Let us start with the very basics: installation and then the pure ruby language.
Setup MySql
If you use debian as OS it is quite simple to install mysql:
sudo apt-get install mysql-server
Then create a database with the following lines
mysql -u root
-p
type the following in the mysql shell:
CREATE DATABASE mydb;
GRANT ALL PRIVILEGES ON mydb.* TO 'admin'@'localhost' IDENTIFIED BY 'admin' WITH GRANT OPTION;
FLUSH PRIVILEGES;
quit;
Later on you can log into the mysql database via
mysql -u admin -p
[now type the password ‘admin’]
SHOW TABLES FROM mydb;
I suggest you to use http://www.squirrelsql.org/ to view and even manipulate the database. The nice thing about this java program is: you can simply install the jdbc drivers for your database (e.g sqlite or mysql) and after configuring them you can browse the databases in a nice way!
Install Ruby and Rails
To be independend from Java or if you don’t want to use JRuby you have to install ruby on your machine:
sudo apt-get install ruby libzlib-ruby rdoc irb
Now install gems …
sudo apt-get install rubygems
sudo gem install mysql
… and rails
sudo apt-get install rails
Create a Skeleton Application
Optionally install NetBeans 6.1 (and Java >1.5 before) to get some handy functionality.
Be sure that you choose a package with rails or install the rails plugins via: Tools->Plugins.
Now you should able to create a rails application: New Project->Ruby On Rails Application. Click Next and choose your ruby system. (Or do ‘rails testapp’ on the command line).
You will get a list of created files. To quickly navigate to a file in NetBeans press ALT+SHIFT+O (Oh not zero) and type in the name. Now I will go through some of the generated files:
app/controllers/application.rb
This is the base class for all of our controllers. To study the Model-View-Controller pattern visit wikipedia. In our controllers we put in all of our application logic. For example the password encryption when one of our user logs in.
app/helpers/application_helper.rb
In this helper modul we define some convinient methods for our view
test/test_helper.rb
With this class it is easy to test the implemented (helper) methods. Read “Agile Web Development with Rails” to be surprised that unit and even integration tests are very easy (and fast) to write.
config/database.yml
The generated content looks like:
development:
# your database server:
adapter: mysql
encoding: utf8
database: mydb
username: admin
password: admin
timeout: 5000
# necessary if you are on debian:
socket: /var/run/mysqld/mysqld.sock
…
config/routes.rb
Here you will define later more fine grained navigation rules for the pages of your web application.
In NetBeans (with rails of course) database-migrating is very easy: right click the project->Migrate Database->To [misc] Version or Clear…
Start the web server with F6 in NetBeans or type
ruby script\server
Then go to http://localhost:3000/ with your browser and you should see ruby’s welcome page.
Now we want to replace the index.html with an erb (like jsp) file. To do this we will remove the public/index.html file and do
script/generate controller home index
add the following to the routes.rb
map.home '', :controller => 'home', :action => 'index'
To add some more functionality to our rails application there are a lot of plugins available. One of them is the restful_authentication, where a tutorial plugin (or here) exists which itself references to a bunch of other useful plugins. Check them out!.
Now some comments on setting up the restful_authentication plugin: Add the following resource to your repositories if you need this plugin (and others from the author):
script/plugin source http://svn.techno-weenie.net/projects/plugins/script/plugin install restful_authentication
or simply do
script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/
On my machine it took a lot of time and finished with an timeout error so I did:
sudo apt-get install git-corecd vendor/plugin && git clone git://github.com/activefx/restful_authentication.gitmv restful-authentication/ restful_authentication/ && cd ../..
Now generate the necessary classes:
script/generate authenticated user sessions --include-activation --stateful
My (unsorted) Comments
Try getting started with rails and come back here to read the following comments (or post your own!) if you figured out sth. worth enough to be said for beginners.
- For restful_authentication:
Be sure that you ignore the config/initializers/site_keys.rb in your subversion!! But save it, because you will need it for your application!
- If need a login snippet like the one from the authentication tutorial:
app/views/users/_user_bar.html.erb in your start up weü page app/views/home/index.html.erb
Use the following line:
<%= render(:partial => “users/user_bar”) %>
- If you need ssh2 try:
# require ‘digest/sha1’
require ‘digest/sha2’
def User.mydigest(str)
Digest::SHA256.digest(str)
#Digest::SHA1.hexdigest(str)
end
- What the hell is this string with a colon? I mean the ‘:password’ here:
update_attributes :password => ‘secure’
It is called symbol and is the name of a variable e.g. of a class. Where ‘secure’ is the value of the variable password. So with this method call e.g. within the User class you do password = ‘secure’.
Example:
var = { ‘a’ => ‘b’, 1 => ‘c’}
assert_equals(‘b’, var[‘a’])
- And what is the :password => ‘secure’ statement?
This is a key => value expression without the {} braces of the hash (Map in Java) , which are optional if the hash is the last parameter. This is very handy if you have several properties to set.
- What is ‘self’? It depends! Read more about self here!
- global variables begins with @@
- object variables begins with an @ (All the instance methods of a class can access this variable. So every object has its own set of object variables.)
- local variable begins with a lower case character (except ‘self’)
- constant variables begins with an upper case character (except ‘:symbol’)
Warning: if you don’t add self in front of you object variables, ruby assumes that they are local!?
- What is attr_accessor :name? This will create a getter and a setter for the variable ‘name’.
Or define a setter manually (via operator overloading)
def volume=(vol)
leftChannel = self.rightChannel = vol
end
- Where is the constructor of User? Do
user = User.new
- escape html in the view via h(user_input).
For more security related stuff look here, here and here.
- The following line is not always secure (‘mass assignment’)
User.new(params[:user])
To make it secure do:
attr_accessible :name
Now only the variable name can be change via url parameters.
- The following statement is unsecure
User.find(:all, :conditions => [“name like ‘%#{params[:query]}%'”])
Use
:conditions => “name like ?”, ‘%’ + params[:query] + ‘%’
- add filter_parameter_logging :password to application.rb
=> all fields with names like “password” will get [FILTERED] in the logs
- Rails add a very handy method to objects:
o.blank?
An object is blank if it‘s false, empty, or a whitespace string. For example, “”, ” “, nil, [], and {} are blank. Taken from here.
- There is no counter++
Use counter += 1
- Swapping variables:
a, b = b, a
This work in methods too! E.g. return a pair of variables via
def meth
return a, b
end
Now call the method
b, a = meth
- if sugar – ‘the other wayround’
puts ‘hello world’ if str == ‘name’
- defined? var
will return true if there is a field named var
- You can use ‘hello’ or “hello”
The only difference for those strings is the expression evaluation like “#{var}”
This will work only in “”
- comments are like in bash: #
Or use this to comment several lines:
=begin
here is comment
here too. WARING: =begin and =end has to be the first characters on the lines!
=end
- Default values for method parameters via
def meth(param=’test’)
end
- def see_how_to_throw
begin
# Do something nifty
raise SomeError, “This is the error message!”
rescue SomeError
# This is executed when a SomeError exception is raised
# to rethrow do
# raise $!
rescue AnotherError => error
# Here, the exception object is referenced from the
# `error’ variable
else
# This is executed only if no exceptions were raised
ensure
# This is always executed, exception or not
end
end
- A very useful tool for testing is autotest:
gem install ZenTest
- It is eays to test with rails! Very easy to write unit and functional testing of your controllers and the pages.
In NetBeans press ALT+F6 to start them.
- use %{ } for xml strings directly unescaped in the code! Very handy.
- Time sugar:
3.minutes + 3.hours
returns the result in seconds! Much more …
- counter ||= 0
This statement will only be executed if counter is nil. Useful for singletons you think? Use self for this!
- Unicode support is not that good. Use Chars instead of the built in String class. Or convert to Chars before working with strings.
- Why are there named routes in routes.rb?
These routes are accessible from the view. E.g. the following line is a named route (map.hello instead of map.resource)
map.hello ‘/fhello’, :controller => ‘users’, :action => ‘hello’
So the method hello will be invoke if the user click the link in the view which is generated via <%=hello_url%>
One special name ‘map.resources’ indicates that rails should create 7 standard routes (4 of them are the CRUD methods). For example map.resources :articles will create the following routes:
/articles (GET=>shows all, POST=>create a new)
/articles/new (shows html for new article)
/articles/1 (GET=>shows the first article, PUT=>update, DELETE=>deletes the article)
/articles/1;edit
- parsing invalid xml with require ‘rubygems’ and require ‘rubyful_soup’. Then do:
xml_data = Net::HTTP.get_response(URI.parse(url)).body
doc = BeautifulSoup.new(xml_data)